package com.young.ums.service.impl;

import com.young.common.exception.BaseException;
import com.young.common.util.CommonUtil;
import com.young.common.core.dal.service.IDataAccessService;
import com.young.common.util.Page;
import com.young.common.util.StringUtils;
import com.young.interfaces.log.annotation.Log;
import com.young.ums.core.ETopic;
import com.young.ums.core.ISubscriber;
import com.young.ums.model.*;
import com.young.ums.model.enums.ERoleOpenTypeEnum;
import com.young.ums.service.IDeptService;
import com.young.ums.service.IRoleDeptService;
import com.young.ums.service.IRoleService;
import com.young.ums.util.UmsConstants;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
* 角色的可用单位关联信息服务实现
* Created by imrookie on 2018-11-13.
*/
@Service("roleDeptService")
public class RoleDeptServiceImpl implements IRoleDeptService,ISubscriber {

    @Resource(name = "dataAccessService")
    IDataAccessService dataAccessService;//数据层服务

    @Resource
    IDeptService deptService;

    @Resource
    IRoleService roleService;

    private static final Logger logger = LoggerFactory.getLogger(RoleDeptServiceImpl.class);

    private static final String MAPPER = "com.young.ums.mapper.roleDept";//mapper的namespace

    //获取数据列表
    @Log("查询角色单位关联关系")
    @Override
    public List<RoleDept> getList(RoleDept obj) {
        return dataAccessService.getList(MAPPER + ".getList", obj);
    }

    //获取数据列表(分页)
    @Log("分页查询角色单位关联关系")
    @Override
    public List<RoleDept> getPage(RoleDept obj, Page page) {
        return dataAccessService.getList(MAPPER + ".getList", obj, page);
    }

    //查询单条
    @Log("查询角色单位关联关系")
    @Override
    public RoleDept get(String id) {
        return dataAccessService.getObject(MAPPER + ".get", id);
    }

    //统计数量
    @Log("计数角色单位关联关系")
    @Override
    public int count(RoleDept obj) {
        return dataAccessService.getObject(MAPPER + ".count", obj);
    }

    //修改
    @Log("修改角色单位关联关系")
    @Override
    public int update(RoleDept obj) {
        return dataAccessService.update(MAPPER + ".update", obj);
    }

    //批量删除
    @Log("批量删除角色单位关联关系")
    @Override
    public int delete(String[] idArr) {
        int i = 0;
        for(String id : idArr){
            i += this.delete(id);
        }
        return i;
    }

    /**
     * 删除角色相关的所有关联信息
     *
     * @param roleId 角色id
     * @return
     */
    @Log("根据角色id删除角色单位关联关系")
    @Override
    public int deleteByRoleId(String roleId) {
        return dataAccessService.delete(MAPPER + ".deleteByRoleId", roleId);
    }

    /**
     * 删除单位相关联的所有关联信息
     *
     * @param deptId 单位id
     * @return
     */
    @Log("根据单位id删除角色单位关联关系")
    @Override
    public int deleteByDeptId(String deptId) {
        return dataAccessService.delete(MAPPER + ".deleteByDeptId", deptId);
    }

    //删除单条
    @Log("删除角色单位关联关系")
    @Override
    public int delete(String id) {
        return dataAccessService.delete(MAPPER + ".delete", id);
    }

    //插入
    @Log("插入删除角色单位关联关系")
    @Override
    public int insert(RoleDept obj) {
        if (StringUtils.isBlank(obj.getId())){
            obj.setId(CommonUtil.getUUID());
        }
        return dataAccessService.insert(MAPPER + ".insert", obj);
    }

    //批量插入
    @Log("批量插入角色单位关联关系")
    @Override
    public int batchInsert(List<RoleDept> list) {
        int i = 0;
        for(RoleDept item : list){
            i += this.insert(item);
        }
        return i;
    }

    /**
     * 批量关联单位(N)到角色(1)
     *
     * @param roleId  角色id
     * @param deptIds 单位id数组
     * @return
     */
    @Log("批量关联单位(N)到角色(1)")
    @Override
    public int relevanceDepts2Role(String roleId, String[] deptIds) {
        int i = 0;
        Role role = roleService.get(roleId);
        if (role == null) {
            throw new BaseException("关联角色不存在");
        }
        //清空原有关联
        this.deleteByRoleId(roleId);
        //插入新关联
        if (StringUtils.isNotBlank(roleId) && deptIds != null && deptIds.length > 0){
            for (String deptId : deptIds){
                /*//判断是否已经存在关联
                if (this.isRelevanced(roleId, deptId)){
                    logger.info("[批量关联单位到角色] 角色[{}]与单位[{}]已经存在关联关系,跳过.", roleId, deptId);
                    continue;
                }*/
                if (deptId.equals(role.getCompanyId())) {
                    logger.info("[批量关联单位到角色] 角色[{}]归属于单位[{}],不需要记录关联关系,跳过.", roleId, deptId);
                    continue;
                }
                RoleDept roleDept = new RoleDept();
                roleDept.setRoleId(roleId);
                roleDept.setDeptId(deptId);
                i += this.insert(roleDept);//插入关联关系
            }
        }
        return i;
    }

    /**
     * 判断指定角色和单位是否存在关联
     *
     * @param roleId 角色id
     * @param deptId 单位id
     * @return
     */
    @Log("判断指定角色和单位是否存在关联")
    @Override
    public boolean isRelevanced(String roleId, String deptId) {
        RoleDept roleDept = new RoleDept();
        roleDept.setRoleId(roleId);
        roleDept.setDeptId(deptId);
        return this.count(roleDept) > 0;
    }

    /**
     * 根据角色id查询单位id集合
     *
     * @param roleId 角色id
     * @return
     */
    @Log("根据角色id查询单位id集合")
    @Override
    public List<String> getDeptIdListByRoleId(String roleId) {
        return dataAccessService.getList(MAPPER + ".getDeptIdListByRoleId", roleId);
    }

    /**
     * 根据单位id查询角色id集合
     *
     * @param deptId 单位id
     * @return
     */
    @Log("根据单位id查询角色id集合")
    @Override
    public List<String> getRoleIdListByDeptId(String deptId) {
        return dataAccessService.getList(MAPPER + ".getRoleIdListByDeptId", deptId);
    }

    /**
     * 根据单位id集合查询关联的角色id集合
     *
     * @param companyIds 单位id集合
     * @return
     */
    @Log("根据单位id集合查询关联的角色id集合")
    @Override
    public List<String> getRoleIdListByDeptIds(List<String> companyIds) {
        return dataAccessService.getList(MAPPER + ".getRoleIdListByDeptIds", companyIds);
    }

    /**
     * 根据角色id查询关联的单位信息
     *
     * @param roleId 角色id
     * @return
     */
    @Log("根据角色id查询关联的单位信息")
    @Override
    public List<Dept> getCompanyListByRoleId(String roleId) {
        //查询角色信息
        Role role = roleService.get(roleId);
        //当角色向部分下级开放时,查询单位信息
        if (role != null && ERoleOpenTypeEnum.SOME_CHILD.eq(role.getOpen())){
            //根据角色id查询关联的单位id
            List<String> companyIds = this.getDeptIdListByRoleId(roleId);
            if (companyIds != null && companyIds.size() > 0){
                //根据id查询单位信息
                return deptService.getListByIds(companyIds.toArray(new String[]{}));
            }
        }
        return null;
    }

    /**
     * 根据单位id集合查询关联的角色信息
     * @param companyIds 单位id集合
     * @return
     */
    @Log("根据单位id集合查询关联的角色信息")
    @Override
    public List<Role> getRoleListByCompanyIds(List<String> companyIds){
        List<String> list = this.getRoleIdListByDeptIds(companyIds);
        if (list != null && list.size() > 0) {
            return roleService.getListByIds(list);
        }
        return null;
    }

    /**
     * 返回订阅的主题数组
     */
    @Override
    public ETopic[] topics() {
        return new ETopic[]{ETopic.ROLE_DEL, ETopic.DEPT_DEL, ETopic.ROLE_OPEN_TO_SOME_CHILD_CHANGE};
    }

    /**
     * 消费
     *
     * @param topic   主题
     * @param message 传输对象
     */
    @Override
    public void consume(ETopic topic, Object message) {
        try {
            if (topic == ETopic.ROLE_DEL){
                this.deleteByRoleId(message.toString());
            } else if (topic == ETopic.DEPT_DEL){
                this.deleteByDeptId(message.toString());
            } else if (topic == ETopic.ROLE_OPEN_TO_SOME_CHILD_CHANGE){//向部分下级单位公开变了,删除已有的角色的关联关系
                this.deleteByRoleId(message.toString());
            }
        } catch (Exception e) {
            logger.info("[UMS消息消费-RoleDeptServiceImpl] 消费异常,主题={},消息={}", topic, message, e);
            throw new BaseException(e);
        }
    }
}